/**
   Copyright 2011 Attila Fekete

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
 */

package org.afekete.filecompareprocessor;

import java.io.File;
import java.io.IOException;
import java.util.List;

import javax.xml.bind.JAXBException;
import javax.xml.stream.XMLStreamException;

import org.afekete.filecompareprocessor.action.FileAction;
import org.afekete.filecompareprocessor.action.FileAction.ActionType;
import org.afekete.filemetadatacreator.FileMetaDataCreator;
import org.afekete.filemetadatacreator.generated.Metadatacollection.Metadata;

/**
 * This controller class take care of processing input parameters
 * and executes the required action on files based on the result of comparison 
 * of various file versions.
 * 
 * Usage:
 * java -jar FileMetaDataCreator.jar -options <action> <action_parameters> <primary_parameters> <secondary_parameters>
 * 
 * <action> - Action to be taken if equal items found in primary and secondary versions
 * 0 - copy the secondary version item
 * 1 - move the secondary version item
 * 2 - delete the secondary version item 
 * 
 * <action_parameters> - The input parameters for an action
 * Action parameters for action:
 * 0 - <path_to_copy_to>###<create_structure>###<version>
 * 1 - <path_to_move_to>###<create_structure>###<version>
 * path_to_move_to - the path to move the found items to
 * create_structure - create file structure of primary/seconday version to move the found items into, possible values: true/false
 * version - if create_structure = true tells structure of which version have to be used, possible values: p/s
 * 2 - blank (skip this parameter)
 * 
 * <primary/secondary_parameters> - The parameters defining which files to create meta data for and what must be the outputh pathfilename  
 * 	-options###<output_xml_filename>###<path_to_the_files>###<filename_with_optional_wildcards>
 *  -options###<output_xml_filename>###<pathfilename>
 *  -options###<output_xml_filename>
 *  Attention:
 *	<filename_with_optional_wildcards> - The \ (backslash) character must be used before wildcard characters in this paramater
 * 
 * @author afekete
 *
 */
public class Controller {
	
	public static void main(String[] args) {
		process(args);
		System.exit(0);
	}
	
	/**
	 * Executes processing of the input parameters and executes the required action.
	 * 
	 * @param args command line parameters with all the input file information and action information
	 * @throws JAXBException If something went wrong while exporting objects to XML documents and importing objects from XML documents
	 * @throws XMLStreamException If something went wrong while reading XML documents 
	 * @throws IOException If something went wrong during execution of file operations
	 */
	public static void process(String[] args) {
		
		int actualParameter = 0;
		for (; actualParameter < args.length && !args[actualParameter].endsWith("-options"); actualParameter++);
		
		if (actualParameter == args.length) System.exit(1); // TODO some error message
		if (args.length < 3 + ++actualParameter) System.exit(1); //TODO some error message

		int actionIndex = - 1;
		String aParameters = null;
		String pParameters = null;
		String sParameters = null;
		
		actionIndex = Integer.parseInt(args[actualParameter++]);
		if (FileAction.actions[actionIndex] == ActionType.DELETE_SECONDARY_VERSION_ITEM) actualParameter++;
		else aParameters = args[actualParameter++];
		pParameters = args[actualParameter++];
		sParameters = args[actualParameter++];
		
		try {
			FileAction action = processActionParameters(actionIndex, aParameters);
			List<Metadata> primaryDataList = processVersionParameters(pParameters);
			List<Metadata> secondaryDataList = processVersionParameters(sParameters);
			action.setPrimaryDataList(primaryDataList);
			action.setSecondaryDataList(secondaryDataList);
			String pvPath = getVersionPath(pParameters);
			String svPath = getVersionPath(sParameters);
			action.setPvPath(pvPath);
			action.setSvPath(svPath);
			action.executeAction();
		} catch (JAXBException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (XMLStreamException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
	
	/**
	 * Parses version parameters and processes the second parameter (path) 
	 * to return the version path.
	 * 
	 * @param parameters version patameters
	 * @return version path
	 * @throws JAXBException If something went wrong while loaded xml data into objects 
	 * @throws XMLStreamException If something went wrong during reading the xml file
	 * @throws IOException If a file operation has failed
	 */
	private static String getVersionPath(String parameters) throws JAXBException, XMLStreamException, IOException {
		String[] array = parameters.split("###");
		if (array.length < 3) System.exit(1); //TODO some error message
		File path = new File(array[2]);
		String pathString = path.isDirectory() ? path.getAbsolutePath() : path.getParent();
		return pathString;
	}

	/**
	 * Parses and processes the input parameters of a file version. 
	 * Such parameters are path, filename, output XML filename. 
	 * Output of this operation is an XML file with meta data of files.
	 * 
	 * @param parameters file version input parameters
	 * @return list of MetaData objects
	 * @throws JAXBException
	 * @throws XMLStreamException
	 * @throws IOException
	 */
	private static List<Metadata> processVersionParameters(String parameters) throws JAXBException, XMLStreamException, IOException {
		String[] array = parameters.split("###");
		if (array.length < 2) System.exit(1); //TODO some error message
		String pathFileName = array[1];
		/*
		 * If args.length == 2 then only metadata xml filename is given as parameter.
		 * This means that it already exists and there is no need to create it.
		 */
		if (array.length > 2) FileMetaDataCreator.create(array);
		return XMLImporter.read(new File(pathFileName));
	}

	/**
	 * Parses action input parameters and creates an executable FileAction object.
	 * 
	 * @param actionIndex <code>FileAction.actions</code> index
	 * @param parameters action parameters
	 * @return parameterized FileAction object
	 */
	private static FileAction processActionParameters(int actionIndex, String parameters) {
		
		FileAction action = new FileAction();
		// Setting action type
		action.setAction(FileAction.actions[actionIndex]);
		
		if (parameters == null) return action;
		
		String[] array = parameters.split("###");
		if (array.length < 2) System.exit(1); //TODO some error message
		
		// Setting path
		action.setPath(array[0]);
		// Setting createStructure attribute
		boolean cs = Boolean.valueOf(array[1]);
		action.setCreateStructure(cs);
		// Setting structure value if createStructure is enabled
		if (cs) {
			if (array.length < 3 || array[2].isEmpty()) System.exit(1);	//TODO some error message
			char v = array[2].charAt(0);
			if (v != 'p' && v != 's') System.exit(1);	//TODO some error message
			action.setVersion(v);
		}
		
		return action;
	}
}
